#ifndef __SMEG_EDITOR_CANVAS_HPP__
#define __SMEG_EDITOR_CANVAS_HPP__

////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <vector>

#include <SFML/System/Clock.hpp>
#include <SFML/System/Vector2.hpp>

#include "wxSFMLCanvas.hpp"
#include "SmegPlaceable.hpp"

namespace smeg {
    namespace light {
        class LightSystem;
    }
    namespace core {
        class PlaceableObject;
        class EntityManager;
    }
}

////////////////////////////////////////////////////////////
/// SmegEditorCanvas is a specialized class of wxSFMLCanvas
////////////////////////////////////////////////////////////
class SmegEditorCanvas :
    public wxSFMLCanvas
{
public:
    ////////////////////////////////////////////////////////////
    /// Construct the SmegEditorCanvas
    ///
    /// \param Parent :   Parent of the control (NULL by default)
    /// \param Id :       Identifier of the control (-1 by default)
    /// \param Position : Position of the control (wxDefaultPosition by default)
    /// \param Size :     Size of the control (wxDefaultSize by default)
    /// \param Style :    Style of the control (0 by default)
    ///
    ////////////////////////////////////////////////////////////
                                            SmegEditorCanvas(   wxWindow*       Parent      = NULL, 
                                                                wxWindowID      Id          = -1, 
                                                                const wxPoint&  Position    = wxDefaultPosition, 
                                                                const wxSize&   Size        = wxDefaultSize, 
                                                                long            Style       = 0);
    
    ////////////////////////////////////////////////////////////
    /// Destructor
    ///
    ////////////////////////////////////////////////////////////
    virtual                                 ~SmegEditorCanvas();

    ////////////////////////////////////////////////////////////
    /// Set the selected object
    ///
    /// \param _pSelected :  The selected object
    ///
    ////////////////////////////////////////////////////////////
    void                                    SetSelectedObject( smeg::core::PlaceableObject* _pSelected );

    ////////////////////////////////////////////////////////////
    /// Set the selected objects
    ///
    /// \param _Selected :  The selected objects
    ///
    ////////////////////////////////////////////////////////////
    void                                    SetSelectedObjects( const std::vector< smeg::core::PlaceableObject* >& _Selected );

    ////////////////////////////////////////////////////////////
    /// Get the selected objects
    ///
    /// \return The selected objects
    ///
    ////////////////////////////////////////////////////////////
    const std::vector< smeg::core::PlaceableObject* >& GetSelectedObjects() const;
                        
    ////////////////////////////////////////////////////////////
    /// The selected object was moved
    ///
    /// \param _Move :  The move vector of the object
    ///
    ////////////////////////////////////////////////////////////
    void                                    OnObjectMove( const sf::Vector2f& _Move );
                        
    ////////////////////////////////////////////////////////////
    /// The selected object was rotated
    ///
    /// \param _rot :  The rotation of the object
    ///
    ////////////////////////////////////////////////////////////
    void                                    OnObjectRotate( float _rot );

    ////////////////////////////////////////////////////////////
    /// Reset the selected objects
    ///
    ////////////////////////////////////////////////////////////
    void                                    ResetSelectedObjects();

    ////////////////////////////////////////////////////////////
    /// Set if we update the entities or not
    ///
    /// \param _bUpdate :  True if we update the entities, otherwise false
    ///
    ////////////////////////////////////////////////////////////
    void                                    UpdateEntities( bool _bUpdate );

    ////////////////////////////////////////////////////////////
    /// Get if we update the entities or not
    ///
    /// \return If we update the entities or not
    ///
    ////////////////////////////////////////////////////////////
    bool                                    DoesUpdateEntities() const;

    ////////////////////////////////////////////////////////////
    /// Set if we show the quad tree or not
    ///
    /// \param _bShow :  True if we show the quad tree, otherwise false
    ///
    ////////////////////////////////////////////////////////////
    void                                    ShowQuadTree( bool _bShow );

    ////////////////////////////////////////////////////////////
    /// Get if we show the quad tree or not
    ///
    /// \return If we show the quad tree or not
    ///
    ////////////////////////////////////////////////////////////
    bool                                    DoesShowQuadTree() const;

    ////////////////////////////////////////////////////////////
    /// Set if we show the profiler info or not
    ///
    /// \param _bShow :  True if we show the profiler, otherwise false
    ///
    ////////////////////////////////////////////////////////////
    void                                    ShowProfiler( bool _bShow );

    ////////////////////////////////////////////////////////////
    /// Get if we show the profiler or not
    ///
    /// \return If we show the profiler or not
    ///
    ////////////////////////////////////////////////////////////
    bool                                    DoesShowProfiler() const;

    ////////////////////////////////////////////////////////////
    /// Get the current center of the canvas
    ///
    /// \return The current center of the canvas
    ///
    ////////////////////////////////////////////////////////////
    const sf::Vector2f&                     GetViewCenter() const;

private :
    ////////////////////////////////////////////////////////////
    void                                    UpdateParentWindow();
    void                                    EndDrag();
    
    ////////////////////////////////////////////////////////////
    /// Notification for the derived class that moment is good
    /// for doing its update and drawing stuff
    ///
    ////////////////////////////////////////////////////////////
    virtual void                            OnUpdate();
    
    ////////////////////////////////////////////////////////////
    /// Events
    ///
    ////////////////////////////////////////////////////////////
    void                                    OnKeyDown( wxKeyEvent& event );
    void                                    OnKeyUp( wxKeyEvent& event );

    void                                    OnMouseLeftDown( wxMouseEvent& event );
    void                                    OnMouseLeftUp( wxMouseEvent& event );
    void                                    OnMouseEnterWindow( wxMouseEvent& event );
    void                                    OnMouseLeaveWindow( wxMouseEvent& event );
    void                                    OnMouseMiddleDown( wxMouseEvent& event );
    void                                    OnMouseMove( wxMouseEvent& event );
    void                                    OnMouseWheel( wxMouseEvent& event );
    virtual void                            OnSizeEnd( wxTimerEvent& event );

    /******************* Protected members ********************/
    wxPoint                                 m_LastMousePos;
    
    bool                                    m_bUpdateEntities;
    bool                                    m_bShowQuadTree;
    bool                                    m_bShowProfiler;
    smeg::light::LightSystem*               m_LightSystem;
    smeg::core::EntityManager*              m_EntityManager;
    
    SmegPlaceable*                          m_pWidgetDragged;
    smeg::core::PlaceableObject*            m_pPlaceableDragged;
    std::vector< SmegPlaceable >            m_PlaceableWidgets;
    std::vector< smeg::core::PlaceableObject* >   m_SelectedObjects;
    
    bool                                    m_isControlDown;

    // DEBUG Info
    sf::View                                m_infoView;
    sf::Clock                               m_clock;
    sf::Font                                m_font;
    sf::Text                                m_info;
};

/************************** Inline ************************/
////////////////////////////////////////////////////////////
/// Set if we show the quad tree or not
////////////////////////////////////////////////////////////
inline void SmegEditorCanvas::UpdateEntities( bool _bUpdate ) {
    m_bUpdateEntities = _bUpdate;
}

////////////////////////////////////////////////////////////
/// Get if we show the quad tree or not
////////////////////////////////////////////////////////////
inline bool SmegEditorCanvas::DoesUpdateEntities() const {
    return m_bUpdateEntities;
}

////////////////////////////////////////////////////////////
/// Set if we show the quad tree or not
////////////////////////////////////////////////////////////
inline void SmegEditorCanvas::ShowQuadTree( bool _bShow ) {
    m_bShowQuadTree = _bShow;
}

////////////////////////////////////////////////////////////
/// Get if we show the quad tree or not
////////////////////////////////////////////////////////////
inline bool SmegEditorCanvas::DoesShowQuadTree() const {
    return m_bShowQuadTree;
}

////////////////////////////////////////////////////////////
/// Set if we show the profiler or not
////////////////////////////////////////////////////////////
inline void SmegEditorCanvas::ShowProfiler( bool _bShow ) {
    m_bShowProfiler = _bShow;
}

////////////////////////////////////////////////////////////
/// Get if we show the profiler or not
////////////////////////////////////////////////////////////
inline bool SmegEditorCanvas::DoesShowProfiler() const {
    return m_bShowProfiler;
}

////////////////////////////////////////////////////////////
/// Get the current center of the canvas
////////////////////////////////////////////////////////////
inline const sf::Vector2f& SmegEditorCanvas::GetViewCenter() const {
    return m_currentView.getCenter();
}

#endif // __SMEG_EDITOR_CANVAS_HPP__
